Skip to content

A tab's root replaced while More holds it is written into More - #539

Open
ide wants to merge 1 commit into
mainfrom
ide/more-root-replaced
Open

ide wants to merge 1 commit into
mainfrom
ide/more-root-replaced

Conversation

@ide

@ide ide commented Nov 13, 2026

Copy link
Copy Markdown
Member

Why

More holds a tab's root and the routes above it once a row of its list is picked. When the app replaced that root (a fresh entry, as open makes for another URL), the old root's node left the tree, so moreTab, which names the tab of More's first route by the tabpanel holding its node, named none. syncTabs then wrote the new root into the tab's own controller while More still showed the old one.

How

Each route's controller records the tabpanel it was last projected from (RouteController.panel), and tabIndex(ofRoute:) falls back to it once the route's node has left the tree. moreTab then names the tab while More holds its replaced root, and the sync writes the new root into More, where UIKit holds the tab's routes. NavigationMoreIOSTests.testATabsRootReplacedWhileMoreHoldsItIsWrittenIntoMore opens Five anew at another URL from its root under More (the More fixture's Renew) and checks that More shows the new root and Five's own controller holds none of its routes. QUEUE.md drops the item.

Test Plan

On main (1229a5be4c), on an iPhone 18 Pro simulator (iOS 27.0), NavigationMoreIOSTests, NavigationSequenceIOSTests, NavigationPopIOSTests, UIKitTabFactsIOSTests, NavigationTabsIOSTests, TabStacksIOSTests and TabsIOSTests pass bare and hosted, run through xcodebuild test-without-building with the run files, fixture environment and accessibility setting bun host/apple/build.mjs --test --ios gives them. NavigationTabsIOSTests.testSharePresentsOverAnAppOwnedTabContainer is left out: on this simulator it has hung in UIActivityViewController's presentation, waiting for sharingd. The iPad sidebar case and the height-only size class case skip on the iPhone. Without the fallback, testATabsRootReplacedWhileMoreHoldsItIsWrittenIntoMore fails: More holds the old root, and Five's own controller holds the new one. bun host/apple/build.mjs --tvos --no-install compiles, and bun scripts/caps.mjs passes.

@ide
ide force-pushed the ide/more-root-replaced branch 2 times, most recently from e7fc44d to 7a0f0ad Compare November 13, 2026 22:58
Why
===

More holds a tab's root and the routes above it once a row of its list is picked. When the app replaced that root (a fresh entry, as `open` makes for another URL), the old root's node left the tree, so `moreTab`, which names the tab of More's first route by the tabpanel holding its node, named none. `syncTabs` then wrote the new root into the tab's own controller while More still showed the old one.

How
===

Each route's controller records the tabpanel it was last projected from (`RouteController.panel`), and `tabIndex(ofRoute:)` falls back to it once the route's node has left the tree. `moreTab` then names the tab while More holds its replaced root, and the sync writes the new root into More, where UIKit holds the tab's routes. `followMore`, `followSelection` and `declineMoreRow` read the same lookup through `tabIndex(ofShown:)`, so they too map a route More shows that the app replaced or removed to its tab. `NavigationMoreIOSTests.testATabsNewRootIsWrittenIntoMoreWhileMoreHoldsTheOldOne` opens Five at another URL from its root under More (the More fixture's Renew) and checks that More shows the new root and Five's own controller holds none of its routes.

Test Plan
===

With this change on `main` `1229a5be4c`, on an iPhone 18 Pro simulator (iOS 27.0), `NavigationMoreIOSTests`, `NavigationSequenceIOSTests`, `NavigationPopIOSTests`, `UIKitTabFactsIOSTests`, `NavigationTabsIOSTests`, `TabStacksIOSTests` and `TabsIOSTests` pass bare and hosted, run through `xcodebuild test-without-building` with the run files, fixture environment and accessibility setting `bun host/apple/build.mjs --test --ios` gives them. `NavigationTabsIOSTests.testSharePresentsOverAnAppOwnedTabContainer` is left out: on this simulator it has hung in `UIActivityViewController`'s presentation, waiting for `sharingd`. The iPad sidebar case and the height-only size class case skip on the iPhone. Without the fallback, `testATabsNewRootIsWrittenIntoMoreWhileMoreHoldsTheOldOne` fails: More holds the old root, and Five's own controller holds the new one. `bun host/apple/build.mjs --tvos --no-install` compiles, and `bun scripts/caps.mjs` passes.
@ide
ide force-pushed the ide/more-root-replaced branch from 7a0f0ad to ce2b543 Compare November 14, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants